class ModuleManager {
  constructor() {
    this.modules = new Map()
    this.hooks = new Map()
  }

  register(id, module) {
    if (this.modules.has(id)) {
      console.warn(`Module ${id} already registered`)
      return
    }
    
    this.modules.set(id, {
      id,
      ...module,
      loaded: false,
      instance: null
    })
    
    if (module.hooks) {
      Object.entries(module.hooks).forEach(([hook, handler]) => {
        this.addHook(hook, handler)
      })
    }
  }

  unregister(id) {
    const module = this.modules.get(id)
    if (!module) return
    
    if (module.instance && module.instance.destroy) {
      module.instance.destroy()
    }
    
    this.modules.delete(id)
  }

  async load(id) {
    const module = this.modules.get(id)
    if (!module) {
      throw new Error(`Module ${id} not found`)
    }
    
    if (module.loaded) {
      return module.instance
    }
    
    try {
      await this.runHook('beforeLoad', { moduleId: id })
      
      if (module.init) {
        module.instance = await module.init()
      }
      
      module.loaded = true
      
      await this.runHook('afterLoad', { moduleId: id, instance: module.instance })
      
      return module.instance
    } catch (error) {
      console.error(`Failed to load module ${id}:`, error)
      throw error
    }
  }

  async unload(id) {
    const module = this.modules.get(id)
    if (!module || !module.loaded) return
    
    try {
      await this.runHook('beforeUnload', { moduleId: id })
      
      if (module.instance && module.instance.destroy) {
        await module.instance.destroy()
      }
      
      module.loaded = false
      module.instance = null
      
      await this.runHook('afterUnload', { moduleId: id })
    } catch (error) {
      console.error(`Failed to unload module ${id}:`, error)
    }
  }

  get(id) {
    const module = this.modules.get(id)
    return module ? module.instance : null
  }

  getAll() {
    return Array.from(this.modules.values())
  }

  getLoaded() {
    return Array.from(this.modules.values()).filter(m => m.loaded)
  }

  addHook(name, handler) {
    if (!this.hooks.has(name)) {
      this.hooks.set(name, [])
    }
    this.hooks.get(name).push(handler)
  }

  removeHook(name, handler) {
    const handlers = this.hooks.get(name)
    if (!handlers) return
    
    const index = handlers.indexOf(handler)
    if (index > -1) {
      handlers.splice(index, 1)
    }
  }

  async runHook(name, data) {
    const handlers = this.hooks.get(name)
    if (!handlers) return
    
    for (const handler of handlers) {
      try {
        await handler(data)
      } catch (error) {
        console.error(`Hook ${name} error:`, error)
      }
    }
  }
}

const moduleManager = new ModuleManager()

export default {
  install(Vue) {
    Vue.prototype.$modules = moduleManager
    
    Vue.mixin({
      beforeCreate() {
        if (this.$options.module) {
          const module = this.$options.module
          if (module.id) {
            moduleManager.register(module.id, module)
          }
        }
      }
    })
  },
  
  manager: moduleManager
}